#ifdef WIN32
#define DLL_API __declspec(dllexport)
#endif
#include "CSSocket.h"
#include <string.h>

#ifdef WIN32
static uint32_t s_wsaCounter = 0;
static WSADATA s_wsaData;
static void CleanWSA(void);
static bool SocketInit(CSSocket *pThiz);
static void SocketDestroy(void);
#endif

#pragma pack(1)
struct _CSSocket
{
	SOCKET               m_socket;            //socket descriptor
	SocketErrorType      m_socketErrno;       //last error	
	int32_t              m_socketDomain;      //socket type domain AF_INET, AF_INET6
	SocketType           m_socketType;        //socket type TCP,UDP or RAW
	uint32_t             m_flags;             //socket flags
	uint32_t             m_index;             //socket used index
	struct sockaddr_in   m_serverSockaddr;    //server address
	struct sockaddr_in   m_clientSockaddr;    //client address
	struct hostent       *m_pHE;
	bool                 m_bIsBlocking;       //is socket blocking
	bool                 m_bIsUDPConnect;     //Ture:enable the udp connect function, default is true;
	bool                 m_bConnect;
};
#pragma pack()

static CSSocket* CSSocketCreatePriv(CSSocket *pThiz, SocketType sType);
static bool CSSocketInitialize(CSSocket *pThiz);
static bool ConnectTCP(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort);
static bool ConnectUDP(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort);
static bool ConnectRAW(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort);

DLL_API CSSocket* CSSocketCreate(SocketType sType)
{
	CSSocket *pThiz = NULL;
	do 
	{
		pThiz = CSSocketCreatePriv(pThiz, sType);
		if (NULL == pThiz)
		{			
			break;
		}

		if (false == CSSocketInitialize(pThiz))
		{
			SAFE_FREE(pThiz);
			break;
		}
	} while (0);
	return pThiz;
}

static bool CSSocketInitialize(CSSocket *pThiz)
{	
	return_val_if_fail(pThiz != NULL, false);
	errno = SocketSuccess;

#ifdef WIN32
	if (false == SocketInit(pThiz))
	{
		return false;
	}
#endif

	pThiz->m_socket = socket(pThiz->m_socketDomain, pThiz->m_socketType, 0);
	CSSocketTranslateError(pThiz);

	return (CSSocketIsValid(pThiz));
}

DLL_API CSSocket* CSSocketAccept(CSSocket *pThiz)
{
	CSSocket   *pClientSocket = NULL;
	SOCKET         socket = SocketError;
	SocketErrorType    socketErrno = SocketSuccess;
	socklen_t      nSockLen = 0;

	return_val_if_fail(pThiz != NULL, NULL);
	if (pThiz->m_socketType != SocketTypeTcp)
	{	
		pThiz->m_index++;
		return pThiz;
	}

	pClientSocket = CSSocketCreatePriv(pClientSocket, SocketTypeTcp);
	//--------------------------------------------------------------------------
	// Wait for incoming connection.
	//--------------------------------------------------------------------------
	if (pClientSocket != NULL)
	{
		nSockLen = sizeof(pThiz->m_clientSockaddr);

		errno = 0;
		socket = ACCEPT(pThiz->m_socket, (struct sockaddr *)(&(pThiz->m_clientSockaddr)), (socklen_t *)&nSockLen);

		if (socket != -1)
		{			
			CSSocketSetDescriptor(pClientSocket, socket);
			CSSocketTranslateError(pClientSocket);
			socketErrno = CSSocketGetError(pClientSocket);
			nSockLen = sizeof(struct sockaddr);
			getpeername(pThiz->m_socket, (struct sockaddr *)(&(pClientSocket->m_clientSockaddr)), &nSockLen);
			memcpy((void *)&pClientSocket->m_clientSockaddr, (void *)&pThiz->m_clientSockaddr, nSockLen);

			memset(&pClientSocket->m_serverSockaddr, 0, nSockLen);
			getsockname(pThiz->m_socket, (struct sockaddr *)(&(pClientSocket->m_serverSockaddr)), &nSockLen);
			
		}
		else
		{
			CSSocketTranslateError(pThiz);
			socketErrno = CSSocketGetError(pThiz);
		}	

		if (socketErrno != SocketSuccess)
		{		
			CSSocketClose(&pClientSocket);			
		}
	}

	return pClientSocket;
}

DLL_API bool CSSocketListen(CSSocket *pThiz,const uint8_t *pAddr, int16_t nPort, int32_t nConnectionBacklog)
{
	bool		   bRetVal = false;
#ifdef WIN32
	ULONG          inAddr;
#else
	int32_t          nReuse;
	in_addr_t      inAddr;
	nReuse = IPTOS_LOWDELAY;
#endif

#ifdef LINUX
	SETSOCKOPT(pThiz->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32_t));
	SETSOCKOPT(pThiz->m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32_t));
#endif

	memset(&(pThiz->m_serverSockaddr),0,sizeof(pThiz->m_serverSockaddr));
	pThiz->m_serverSockaddr.sin_family = AF_INET;
	pThiz->m_serverSockaddr.sin_port = htons(nPort);

	if ((pAddr == NULL) || (!strlen((const char *)pAddr)))
	{
		pThiz->m_serverSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	}
	else
	{
		if ((inAddr = inet_addr((const char *)pAddr)) != INADDR_NONE)
		{
			pThiz->m_serverSockaddr.sin_addr.s_addr = inAddr;
		}
	}

	//--------------------------------------------------------------------------
	// Bind to the specified port 
	//--------------------------------------------------------------------------
	if (BIND(pThiz->m_socket, (struct sockaddr *)&(pThiz->m_serverSockaddr), sizeof(pThiz->m_serverSockaddr)) != SocketError)
	{
		if (pThiz->m_socketType == SocketTypeTcp)
		{
			if (listen(pThiz->m_socket, nConnectionBacklog) != SocketError)
			{
				bRetVal = true;
			}
		}  
		else      
		{
			bRetVal = true;
		}
	}

	CSSocketTranslateError(pThiz);

	if (bRetVal == false)
	{
		CSSocketClose(&pThiz);
	}

	return bRetVal;
}

DLL_API bool CSSocketOpen(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort)
{
	bool bRetVal = false;
	socklen_t nSockLen = 0;

	if (CSSocketIsValid(pThiz) == false)
	{
		CSSocketSetError(pThiz, SocketInvalidSocket);
		return bRetVal;
	}

	if (pAddr == NULL)
	{
		CSSocketSetError(pThiz, SocketInvalidAddress);
		return bRetVal;
	}

	if (nPort == 0)
	{
		CSSocketSetError(pThiz, SocketInvalidPort);
		return bRetVal;
	}

	switch (pThiz->m_socketType)
	{
	case SocketTypeTcp :
		{
			bRetVal = ConnectTCP(pThiz, pAddr, nPort);
			break;
		}
	case SocketTypeUdp :
		{
			bRetVal = ConnectUDP(pThiz, pAddr, nPort);
			break;
		}
	case SocketTypeRaw :
		break;
	default:
		break;
	}

	//--------------------------------------------------------------------------
	// If successful then create a local copy of the address and port							
	//--------------------------------------------------------------------------
	if (bRetVal)
	{		
		nSockLen = sizeof(struct sockaddr);
		memset(&(pThiz->m_serverSockaddr), 0, nSockLen);
		
		getsockname(pThiz->m_socket, (struct sockaddr *)&(pThiz->m_serverSockaddr), &nSockLen);
		nSockLen = sizeof(struct sockaddr);
		memset(&(pThiz->m_clientSockaddr), 0, nSockLen);
		if (SocketTypeUdp == pThiz->m_socketType && false == pThiz->m_bIsUDPConnect)
		{

			pThiz->m_clientSockaddr.sin_family = pThiz->m_socketDomain;
			pThiz->m_clientSockaddr.sin_port = htons(nPort);
			pThiz->m_clientSockaddr.sin_addr.s_addr = inet_addr((char*)pAddr);

		}
		else
		{			
			getpeername(pThiz->m_socket, (struct sockaddr *)&(pThiz->m_clientSockaddr), &nSockLen);				
		}
		CSSocketSetError(pThiz, SocketSuccess);	
	}

	return bRetVal;
}

DLL_API void CSSocketTranslateError(CSSocket *pThiz)
{
#ifdef WIN32
	int32_t nError = 0;
#endif // WIN32
	return_if_fail(pThiz != NULL);
#ifdef LINUX
	switch (errno)
	{
	case EXIT_SUCCESS:
		CSSocketSetError(pThiz, SocketSuccess);
		break;
	case ENOTCONN:
		CSSocketSetError(pThiz, SocketNotconnected);
		break;
	case ENOTSOCK:
	case EBADF:
	case EACCES:
	case EAFNOSUPPORT:
	case EMFILE:
	case ENFILE:
	case ENOBUFS:
	case ENOMEM:
	case EPROTONOSUPPORT:
		CSSocketSetError(pThiz, SocketInvalidSocket);
		break;
	case ECONNREFUSED :
		CSSocketSetError(pThiz, SocketConnectionRefused);
		break;
	case ETIMEDOUT:
		CSSocketSetError(pThiz, SocketTimedout);
		break;
	case EINPROGRESS:
		CSSocketSetError(pThiz, SocketEinprogress);
		break;
	case EWOULDBLOCK:
		//		case EAGAIN:
		CSSocketSetError(pThiz, SocketEwouldblock);
		break;
	case EINTR:
		CSSocketSetError(pThiz, SocketInterrupted);
		break;
	case ECONNABORTED:
		CSSocketSetError(pThiz, SocketConnectionAborted);
		break;
	case EINVAL:
	case EPROTO:
		CSSocketSetError(pThiz, SocketProtocolError);
		break;
	case EPERM:
		CSSocketSetError(pThiz, SocketFirewallError);
		break;
	case EFAULT:
		CSSocketSetError(pThiz, SocketInvalidSocketBuffer);
		break;
	case ECONNRESET:
		CSSocketSetError(pThiz, SocketConnectionReset);
		break;
	case ENOPROTOOPT: 
		CSSocketSetError(pThiz, SocketConnectionReset);
		break;
	default:
		CSSocketSetError(pThiz, SocketEunknown);
		break;	
	}
#endif
#ifdef WIN32
	nError = WSAGetLastError();
	switch (nError)
	{
	case EXIT_SUCCESS:
		CSSocketSetError(pThiz, SocketSuccess);
		break;
	case WSAEBADF:
	case WSAENOTCONN:
		CSSocketSetError(pThiz, SocketNotconnected);
		break;
	case WSAEINTR:
		CSSocketSetError(pThiz, SocketInterrupted);
		break;
	case WSAEACCES:
	case WSAEAFNOSUPPORT:
	case WSAEINVAL:
	case WSAEMFILE:
	case WSAENOBUFS:
	case WSAEPROTONOSUPPORT:
		CSSocketSetError(pThiz, SocketInvalidSocket);
		break;
	case WSAECONNREFUSED :
		CSSocketSetError(pThiz, SocketConnectionRefused);
		break;
	case WSAETIMEDOUT:
		CSSocketSetError(pThiz, SocketTimedout);
		break;
	case WSAEINPROGRESS:
		CSSocketSetError(pThiz, SocketEinprogress);
		break;
	case WSAECONNABORTED:
		CSSocketSetError(pThiz, SocketConnectionAborted);
		break;
	case WSAEWOULDBLOCK:
		CSSocketSetError(pThiz, SocketEwouldblock);
		break;
	case WSAENOTSOCK:
		CSSocketSetError(pThiz, SocketInvalidSocket);
		break;
	case WSAECONNRESET:
		CSSocketSetError(pThiz, SocketConnectionReset);
		break;
	case WSANO_DATA:
		CSSocketSetError(pThiz, SocketInvalidAddress);
		break;
	case WSAEADDRINUSE:
		CSSocketSetError(pThiz, SocketAddressInUse);
		break;
	case WSAEFAULT:
		CSSocketSetError(pThiz, SocketInvalidPointer);
		break;
	default:
		CSSocketSetError(pThiz, SocketEunknown);
		break;	
	}
#endif
}

DLL_API int32_t CSSocketReceive(CSSocket *pThiz, int8_t *pBuf, int32_t iSize)
{
	int32_t iRecvByte = 0;
	return_val_if_fail(pThiz != NULL, -2);
	return_val_if_fail(CSSocketIsValid(pThiz) != false, SocketError);
	return_val_if_fail(pBuf != NULL, 0);	

	CSSocketSetError(pThiz, SocketSuccess);

	switch (pThiz->m_socketType)
	{

	case SocketTypeTcp:
		{
			iRecvByte = RECV(pThiz->m_socket, pBuf, iSize, pThiz->m_flags);
			CSSocketTranslateError(pThiz);
			break;
		}
	case SocketTypeUdp:
		{
			uint32_t srcSize;
			srcSize = sizeof(struct sockaddr_in);
			iRecvByte = RECVFROM(pThiz->m_socket, pBuf, iSize, 0, &pThiz->m_clientSockaddr, &srcSize);
			CSSocketTranslateError(pThiz);
			break;
		}
	default:
		iRecvByte = -1;
		break;
	}

	return iRecvByte;
}

DLL_API int32_t CSSocketSend(CSSocket *pThiz, const int8_t *pBuf, size_t bytesToSend)
{
	int32_t iBytesSent = 0;
	return_val_if_fail(pThiz != NULL, -1);
	return_val_if_fail(CSSocketIsValid(pThiz) != false, SocketError);
	return_val_if_fail(pBuf != NULL, 0);	
	CSSocketSetError(pThiz, SocketSuccess);


	switch(pThiz->m_socketType)
	{
	case SocketTypeTcp:
		{
			if (CSSocketIsValid(pThiz))
			{
				if ((bytesToSend > 0) && (pBuf != NULL))
				{
					iBytesSent = SEND(pThiz->m_socket, pBuf, bytesToSend, 0);
					CSSocketTranslateError(pThiz);					
				}
			}
			break;
		}
	case SocketTypeUdp:
		{
			if (CSSocketIsValid(pThiz))
			{
				if ((bytesToSend > 0) && (pBuf != NULL))
				{
					iBytesSent = SENDTO(pThiz->m_socket, pBuf, bytesToSend, 0, &(pThiz->m_clientSockaddr), sizeof(pThiz->m_clientSockaddr));
					CSSocketTranslateError(pThiz);
				}
			}
			break;
		}
	default:
		break;
	}

	return iBytesSent;
}

DLL_API bool CSSocketClose(CSSocket **ppThiz)
{
	bool bRetVal = false;
	CSSocket *pThiz = NULL;
	return_val_if_fail(ppThiz != NULL, false);
	return_val_if_fail(*ppThiz != NULL, false);
	pThiz = *ppThiz;
	pThiz->m_index--;
	if (pThiz->m_index != 0)
	{
		return true;
	}

	if (CSSocketIsValid(pThiz))
	{
		CSSocketShutdown(pThiz, Both);
		if (CLOSE(pThiz->m_socket) !=SocketError)
		{
			pThiz->m_socket = INVALID_SOCKET;
			bRetVal = true;
		}
	}
#ifdef WIN32	
	SocketDestroy();
#endif
	CSSocketTranslateError(pThiz);

	SAFE_FREE(*ppThiz);
	
	return bRetVal;
}

DLL_API bool CSSocketIsValid(CSSocket *pThiz) 
{ 	
	return_val_if_fail(pThiz != NULL, false);
	if (pThiz->m_socket == SocketError)
	{
		CSSocketSetError(pThiz, SocketError);
		return false;
	}	
	return true; 
}

DLL_API void CSSocketSetDescriptor(CSSocket* pThiz, SOCKET sock)
{
	return_if_fail(pThiz != NULL);
	pThiz->m_socket = sock;
	return;
}

DLL_API SocketErrorType CSSocketGetError(CSSocket *pThiz) 
{ 
	return_val_if_fail(pThiz != NULL, SocketEunknown);
	return pThiz->m_socketErrno; 
}

DLL_API bool CSSocketShutdown(CSSocket *pThiz, ShutdownMode nShutdown)
{
	SocketErrorType nRetVal = SocketEunknown;
	return_val_if_fail(pThiz != NULL, false);	
	nRetVal = (SocketErrorType)shutdown(pThiz->m_socket, nShutdown);
	CSSocketTranslateError(pThiz);
	return (nRetVal == SocketSuccess) ? true: false;
}

DLL_API SOCKET CSSocketGetDescriptor(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, SocketError);
	return pThiz->m_socket;
}

DLL_API SocketType GetCSSocketType(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, SocketTypeInvalid);
	return pThiz->m_socketType;
}

DLL_API uint8_t *CSSocketGetClientAddr(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, NULL);
	return (uint8_t *)inet_ntoa(pThiz->m_clientSockaddr.sin_addr);
}

DLL_API int16_t CSSocketGetClientPort(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, 0);
	return ntohs(pThiz->m_clientSockaddr.sin_port);
}

DLL_API uint8_t *CSSocketGetServerAddr(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, NULL);
	return (uint8_t *)inet_ntoa(pThiz->m_serverSockaddr.sin_addr);
}
DLL_API int16_t CSSocketGetServerPort(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, 0);
	return ntohs(pThiz->m_serverSockaddr.sin_port);
}

DLL_API struct sockaddr_in *CSSocketGetClientSockAddr(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, NULL);
	return &pThiz->m_clientSockaddr;
}

DLL_API struct sockaddr_in *CSSocketGetServerockAddr(CSSocket *pThiz)
{
	return_val_if_fail(pThiz != NULL, NULL);
	return &pThiz->m_serverSockaddr;
}

DLL_API void CSSocketSetError(CSSocket *pThiz, SocketErrorType sErrorType)
{
	return_if_fail(pThiz != NULL);
	pThiz->m_socketErrno = sErrorType;
	return;
}

DLL_API void CSSocketSetUdpConnect(CSSocket *pThiz, bool bConnect)
{
	return_if_fail(pThiz != NULL);
	pThiz->m_bIsUDPConnect = bConnect;
}

CSSocket* CSSocketCreatePriv( CSSocket *pThiz, SocketType sType )
{	
	pThiz = (CSSocket*)MALLOC(sizeof(*pThiz));
	return_val_if_fail(pThiz != NULL, NULL);
	memset((void*)pThiz, 0, sizeof(*pThiz));
	pThiz->m_socket = INVALID_SOCKET;
	pThiz->m_socketErrno = SocketInvalidSocket;
	pThiz->m_socketDomain = AF_INET;
	pThiz->m_socketType = SocketTypeInvalid;
	pThiz->m_flags = 0;
	pThiz->m_bIsBlocking = false;
    pThiz->m_index++;
	pThiz->m_bIsUDPConnect = true;
	switch(sType)
	{		
	case SocketTypeTcp: 
		{
			pThiz->m_socketDomain = AF_INET;
			pThiz->m_socketType =SocketTypeTcp;
			break;
		}
	case SocketTypeTcp6: 
		{
			pThiz->m_socketDomain = AF_INET6;
			pThiz->m_socketType = SocketTypeTcp6;
			break;
		}		
	case SocketTypeUdp:
		{
			pThiz->m_socketDomain = AF_INET;
			pThiz->m_socketType = SocketTypeUdp;
			break;
		}
	case SocketTypeUdp6:
		{
			pThiz->m_socketDomain = AF_INET6;
			pThiz->m_socketType = SocketTypeUdp6;
			break;
		}		
	case SocketTypeRaw:
		{
#ifdef LINUX
			pThiz->m_socketDomain = AF_PACKET;
			pThiz->m_socketType = SocketTypeRaw;
#endif
#ifdef WIN32
			pThiz->m_socketType = SocketTypeInvalid;
#endif
			break;
		}
	default:
		pThiz->m_socketType = SocketTypeInvalid;
		break;
	}
	return pThiz;
}
#ifdef WIN32
static bool SocketInit(CSSocket *pThiz)
{
	int err;	
	return_val_if_fail(pThiz != NULL, false);
	if (s_wsaCounter > 0)
	{
		s_wsaCounter ++;
		return true;
	}
	memset(&s_wsaData, 0, sizeof(s_wsaData));
	err = WSAStartup(MAKEWORD(2, 0), &s_wsaData);
	return_val_if_fail(err == 0, false);
	s_wsaCounter++;
	return true;
}

static void SocketDestroy(void)
{
	s_wsaCounter--;
	if (0 == s_wsaCounter)
	{
		atexit(CleanWSA);
	}	
	return;
}

static void CleanWSA(void)
{
	WSACleanup();
	return;
}
#endif

static bool ConnectTCP(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort)
{
	bool           bRetVal = false;
	struct in_addr stIpAddress;
	struct sockaddr_in *pServerSockAddr = &(pThiz->m_serverSockaddr);
	//------------------------------------------------------------------
	// Preconnection setup that must be preformed					 
	//------------------------------------------------------------------
	memset(pServerSockAddr, 0, sizeof(*pServerSockAddr));
	pServerSockAddr->sin_family = AF_INET;

	if ((pThiz->m_pHE = GETHOSTBYNAME(pAddr)) == NULL) 
	{
#ifdef WIN32
		CSSocketTranslateError(pThiz);
#else
		if (h_errno == HOST_NOT_FOUND)
		{
			CSSocketSetError(pThiz, SocketInvalidAddress);
		}
#endif
		return bRetVal;
	}

	memcpy(&stIpAddress, pThiz->m_pHE->h_addr_list[0], pThiz->m_pHE->h_length);
	pServerSockAddr->sin_addr.s_addr = stIpAddress.s_addr;

	if ((int32_t)pServerSockAddr->sin_addr.s_addr == SocketError)
	{
		CSSocketTranslateError(pThiz);
		return bRetVal;
	}

	pServerSockAddr->sin_port = htons(nPort);



	if (CONNECT(pThiz->m_socket, (struct sockaddr*)pServerSockAddr, sizeof(*pServerSockAddr)) == 
		SocketError)
	{
		//--------------------------------------------------------------
		// Get error value this might be a non-blocking socket so we 
		// must first check.
		//--------------------------------------------------------------
		CSSocketTranslateError(pThiz);

		//--------------------------------------------------------------
		// If the socket is non-blocking and the current socket error
		// is SocketEinprogress or SocketEwouldblock then poll connection 
		// with select for designated timeout period.
		// Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.
		//--------------------------------------------------------------
		/*if ((IsNonblocking()) && 
			((GetSocketError() == CSimpleSocket::SocketEwouldblock) || 
			(GetSocketError() == CSimpleSocket::SocketEinprogress)))
		{
			bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());
		}*/
	}
	else
	{
		CSSocketTranslateError((CSSocket*)pThiz);
		bRetVal = true;
	}

	return bRetVal;
}

static bool ConnectUDP(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort)
{
	bool           bRetVal = false;
	struct in_addr stIpAddress;
	struct sockaddr_in *pServerSockAddr = &(pThiz->m_serverSockaddr);

	if (false == pThiz->m_bIsUDPConnect)
	{
		return true;
	}
	
	//------------------------------------------------------------------
	// Preconnection setup that must be preformed					 
	//------------------------------------------------------------------
	memset(pServerSockAddr, 0, sizeof(*pServerSockAddr));
	pServerSockAddr->sin_family = AF_INET;

	if ((pThiz->m_pHE = GETHOSTBYNAME(pAddr)) == NULL) 
	{
#ifdef WIN32
		CSSocketTranslateError(pThiz);
#else
		if (h_errno == HOST_NOT_FOUND)
		{
			CSSocketSetError(pThiz, SocketInvalidAddress);
		}
#endif
		return bRetVal;
	}

	memcpy(&stIpAddress, pThiz->m_pHE->h_addr_list[0], pThiz->m_pHE->h_length);
	pServerSockAddr->sin_addr.s_addr = stIpAddress.s_addr;

	if ((int32_t)pServerSockAddr->sin_addr.s_addr == SocketError)
	{
		CSSocketTranslateError((CSSocket*)pThiz);
		return bRetVal;
	}

	pServerSockAddr->sin_port = htons(nPort);

	if (connect(pThiz->m_socket, (struct sockaddr*)pServerSockAddr, sizeof(*pServerSockAddr)) != 
		SocketError)
	{
		bRetVal = true;	
	}	

	CSSocketTranslateError(pThiz);	

	return bRetVal;
}

static bool ConnectRAW(CSSocket *pThiz, const int8_t *pAddr, int16_t nPort)
{
	bool           bRetVal = false;
	struct in_addr stIpAddress;
	struct sockaddr_in *pServerSockAddr = &(pThiz->m_serverSockaddr);

	memset(pServerSockAddr, 0, sizeof(*pServerSockAddr));
	pServerSockAddr->sin_family = AF_INET;

	if ((pThiz->m_pHE = GETHOSTBYNAME(pAddr)) == NULL) 
	{
#ifdef WIN32
		CSSocketTranslateError((CSSocket*)pThiz);
#else
		if (h_errno == HOST_NOT_FOUND)
		{
			CSSocketSetError(pThiz, SocketInvalidAddress);
		}
#endif
		return bRetVal;
	}

	memcpy(&stIpAddress, pThiz->m_pHE->h_addr_list[0], pThiz->m_pHE->h_length);
	pServerSockAddr->sin_addr.s_addr = stIpAddress.s_addr;

	if ((int32_t)pServerSockAddr->sin_addr.s_addr == SocketError)
	{
		CSSocketTranslateError(pThiz);
		return bRetVal;
	}

	pServerSockAddr->sin_port = htons(nPort);

	if (connect(pThiz->m_socket, (struct sockaddr*)pServerSockAddr, sizeof(*pServerSockAddr)) != 
		SocketError)
	{
		bRetVal = true;	
	}	
	CSSocketTranslateError(pThiz);	

	return bRetVal;	
}

DLL_API int32_t CSSocketSize(void)
{
	return sizeof(struct _CSSocket);
}

